#ifndef __TOUR_H
#define __TOUR_H
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip.h>
#include <time.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/un.h>
#include "lists.h"
#include "unp.h"
#include "hw_addrs.h"

/*This header files contains the data structures needed
 * for the tour file
 */

#define IPPROTO_TOUR 		175
#define MAX_TOUR_NODES 		128
#define MAX_HOST_NAME_SIZE	128
#define IP_SIZE			128
#define IP_ID_VAL		9095

#define PING_TIMEOUT		1
#define MULTICAST_TIMEOUT	5
#define MAX_WAIT_ECHO_REPLIES	5

#define MULTICAST_ADDR		"235.0.0.35"
#define MULTICAST_PORT		19095
#define MULTICAST_MSG_SIZE	256

#define MESSAGE_SIZE		1024
#define TIME_BUF_SIZE 		30
#define MAX_PACKET_SIZE 	8192
#define TTL_OUT			64

/***** From arp.h ******/
#define ETH_ARP_PROTO 9225
#define DOM_SOCK_FILE "arp_group9.txt"
#define ARP_REQUEST 1
#define ARP_REPLY 2
#define ARP_ID 0x9225

typedef struct tour_module_vars {
	int rt_sock;
	int pgin_sock;
	int pgout_sock;
	int mcast_sock;
	int send_ping;
	char host_name[MAX_HOST_NAME_SIZE];
	char host_ip[IP_SIZE];
	u_int16_t pid;
	int ping_sequence_no;
	int is_destination;
	int echo_reply_count;
	uint32_t tour_src_addr;
	char mcast_ip[IP_SIZE];
	unsigned int mcast_port_no;
}TOUR_MODULE_VARS;

typedef struct tour_node {
	unsigned long ip;	
}TOUR_NODE;

typedef struct tour_data {
	unsigned int cur_dest_index;
	unsigned int max_index;
	char mcast_ip[IP_SIZE];
	unsigned int mcast_port_no;
	uint32_t ip[MAX_TOUR_NODES];
}TOUR_DATA;

typedef struct tour_list_entry {
	uint32_t saddr;	
	int id_no;
	struct list_head next;
}TOUR_LIST_ENTRY;

struct hwaddr {
	int             sll_ifindex;	 /* Interface number */
	unsigned short  sll_hatype;	 /* Hardware type */
	unsigned char   sll_halen;	 /* Length of address */
	unsigned char   sll_addr[6];	 /* Physical layer address */
};


 
void handle_rt_sock(TOUR_MODULE_VARS *vars);

void handle_pgin_sock(TOUR_MODULE_VARS *vars);

int handle_mcast_sock(TOUR_MODULE_VARS *vars);
int join_multicast_group(int sockfd, char *mcast_addr);
int add_to_tour_list(TOUR_DATA *tour_data, int index, char *node_name);
int process_input_and_build_tour(int argc, char *argv[], TOUR_MODULE_VARS *global_vars);
int do_start_tour(TOUR_MODULE_VARS *global_vars, TOUR_DATA *tour_data);
int build_and_send_ip_packet(TOUR_MODULE_VARS *global_vars, TOUR_DATA *tour_data, int src_index, int dest_index);
int handle_route_socket(TOUR_MODULE_VARS *tour_vars);
int update_and_send_rt_packet(TOUR_MODULE_VARS *tour_vars, char *buf);
void *do_start_pinging(void *arg);
uint16_t in_cksum(uint16_t *addr, int len);
char *get_host_name_with_netaddr(uint32_t addr);
int check_if_pkt_is_first_time(TOUR_MODULE_VARS *global_vars, uint32_t saddr);
int areq(struct sockaddr *IPaddr, socklen_t sockaddrlen, struct hwaddr *HWaddr);
void get_src_mac(char *);
int begin_mcast(TOUR_MODULE_VARS *tour_vars);
int send_multicast_message(int sockfd, char *msg, char *mcast_addr, unsigned int port, TOUR_MODULE_VARS *vars);
#endif
